package com.llb666.common.core.exception;

import com.llb666.common.core.web.error.CommonError;
import com.llb666.common.core.web.response.BaseResponse;
import com.llb666.common.core.web.response.DataResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;

import javax.servlet.http.HttpServletRequest;
import java.nio.file.AccessDeniedException;
import java.util.List;

/**
 * 全局自定义异常处理.
 *
 * @author llb66
 */
@RestControllerAdvice
public class AppExceptionHandler {

    private static final Logger LOGGER = LoggerFactory.getLogger(AppExceptionHandler.class);

    /**
     * 文件上传异常. MaxUploadSizeExceededException
     */
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public BaseResponse handlerMaxUploadFile(MaxUploadSizeExceededException e) {
        LOGGER.error("文件上传异常:", e);
        return DataResponse.errorMsg("文件上传不能大于500KB");
    }

    /**
     * 未知异常. Exception
     */
    @ExceptionHandler(value = Exception.class)
    public BaseResponse exceptionHandler(HttpServletRequest request, Exception e) {
        LOGGER.error("unknown error:", e);
        return DataResponse.fail(CommonError.UnExpected);
    }

    /**
     * 参数异常. MissingServletRequestParameterException
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request,
                                         MissingServletRequestParameterException e) {
        return DataResponse.fail(CommonError.RequestParamsInvalid);
    }

    /**
     * 未授权异常. AccessDeniedException
     */
    @ExceptionHandler(value = AccessDeniedException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request, AccessDeniedException e) {
        return DataResponse.fail(CommonError.NotAuthorized);
    }

    /**
     * 通用异常. AppException
     */
    @ExceptionHandler(value = AppException.class)
    public BaseResponse domainExceptionHandler(HttpServletRequest request, AppException e) {
        LOGGER.error("domain exception:" + e.getMsg(), e);
        if (StringUtils.isEmpty(e.getMsg())) {
            return DataResponse.fail(e.getErrCode());
        }
        return DataResponse.fail(e.getErrCode(), e.getMsg());
    }

    /**
     * 检验异常. MethodArgumentNotValidException
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public BaseResponse exceptionHandler(HttpServletRequest request,
                                         MethodArgumentNotValidException e) {
        List<ObjectError> errors = e.getBindingResult().getAllErrors();
        String message = this.formatAllErrorMessages(errors);
        return DataResponse.fail(CommonError.RequestParamsInvalid, message);
    }

    private String formatAllErrorMessages(List<ObjectError> errors) {
        StringBuffer errorMsg = new StringBuffer();
        errors.forEach(error ->
                errorMsg.append(error.getDefaultMessage())
        );
        return errorMsg.toString();
    }
}
